BeautifulSoup简介
BeautifulSoup 3只支持python 2,并且已经停止开发,BeautifulSoup支持python2和3,以下使用方法参考4.4版说明文档

BeautifulSoup使用
解析器比较
| 解析器 | 使用方法 | 优势 | 劣势 |
|---|---|---|---|
| Python标准库 | BeautifulSoup(markup,"html.parser") |
Python的内置标准库执行速度适中文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
| lxml HTML 解析器 | BeautifulSoup(markup,"lxml") |
速度快文档容错能力强 | 需要安装C语言库 |
| lxml XML 解析器 | BeautifulSoup(markup,["lxml-xml"])``BeautifulSoup(markup,"xml") |
速度快唯一支持XML的解析器 | 需要安装C语言库 |
| html5lib | BeautifulSoup(markup,"html5lib") |
最好的容错性以浏览器的方式解析文档生成HTML5格式的文档 | 速度慢不依赖外部扩展 |
如果不指定解析器,BeautifulSoup会自动选择最合适的解析器来解析文档
对象种类
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种: Tag , NavigableString , BeautifulSoup , Comment .
Tag
Tag 对象与XML或HTML原生文档中的tag相同:
|
|
每个tag都有name和attribute:
|
|
可以通过直接赋值来增加或修改tag的名字和属性:
|
|
通过del删除属性:
|
|
对于多值属性,会返回一个列表,使用的时候注意是返回列表还是字符串:
|
|
如果转换的文档是XML格式,那么tag中不包含多值属性
|
|
NavigableString
字符串常被包含在tag内.Beautiful Soup用 NavigableString 类来包装tag中的字符串:
|
|
tag中包含的字符串不能编辑,但是可以被替换成其它的字符串,用 replace_with() 方法:
|
|
如果想在Beautiful Soup之外使用 NavigableString 对象,需要调用 unicode() 方法,将该对象转换成普通的Unicode字符串,否则就算Beautiful Soup已方法已经执行结束,该对象的输出也会带有对象的引用地址.这样会浪费内存.
BeautifulSoup
BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法.
因为 BeautifulSoup 对象并不是真正的HTML或XML的tag,所以它没有name和attribute属性.但有时查看它的 .name 属性是很方便的,所以 BeautifulSoup 对象包含了一个值为 “[document]” 的特殊属性 .name
|
|
Comment
|
|
Comment 对象是一个特殊类型的 NavigableString 对象:
|
|
但是当它出现在HTML文档中时, Comment 对象会使用特殊的格式输出:
|
|
遍历文档树
我们测试的文档内容:
|
|
通过点取属性的方式只能获得当前名字的第一个tag:
|
|
使用find_all()获取所有的tag:
|
|
tag的 .contents 属性可以将tag的子节点以列表的方式输出:
|
|
字符串没有 .contents 属性,因为字符串没有子节点:
|
|
通过tag的 .children 生成器,可以对tag的子节点进行循环:
|
|
.descendants 属性可以对所有tag的子孙节点进行递归循环
BeautifulSoup 有一个直接子节点(节点),却有很多子孙节点:
|
|
输出所有string:
|
|
通过 .parent 属性来获取某个元素的父节点.
通过元素的 .parents 属性可以递归得到元素的所有父辈节点
在文档树中,使用 .next_sibling 和 .previous_sibling 属性来查询兄弟节点
通过 .next_siblings 和 .previous_siblings 属性可以对当前节点的兄弟节点迭代输出
.next_element 属性指向解析过程中下一个被解析的对象(字符串或tag),结果可能与 .next_sibling相同,但通常是不一样的.
通过 .next_elements 和 .previous_elements 的迭代器就可以向前或向后访问文档的解析内容,就好像文档正在被解析一样
搜索文档树
除了find_all()之外,搜索也支持正则表达式:
|
|
下面代码找到文档中所有<a>标签和<b>标签:
|
|
True 可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串节点
|
|
如果包含一个名字为 id 的参数,Beautiful Soup会搜索每个tag的”id”属性.
|
|
如果传入 href 参数,Beautiful Soup会搜索每个tag的”href”属性:
|
|
下面的例子在文档树中查找所有包含 id 属性的tag,无论 id 的值是什么:
|
|
使用多个指定名字的参数可以同时过滤tag的多个属性:
|
|
通过 string 参数可以搜搜文档中的字符串内容.与 name 参数的可选值一样, string 参数接受 字符串 , 正则表达式 , 列表, True . 看例子:
|
|
虽然 string 参数用于搜索字符串,还可以与其它参数混合使用来过滤tag.Beautiful Soup会找到.string 方法与 string 参数值相符的tag.下面代码用来搜索内容里面包含“Elsie”的<a>标签:
|
|
限制返回结果的个数:
|
|
下面两行代码是等价的:
|
|
这两行代码也是等价的:
|
|
find_all() 和 find() 只搜索当前节点的所有子节点,孙子节点等. find_parents() 和find_parent() 用来搜索当前节点的父辈节点
find_next_siblings() 方法返回所有符合条件的后面的兄弟节点, find_next_sibling() 只返回符合条件的后面的第一个tag节点.
find_previous_siblings() 方法返回所有符合条件的前面的兄弟节点, find_previous_sibling() 方法返回第一个符合条件的前面的兄弟节点
find_all_next()方法返回所有符合条件的节点, find_next() 方法返回第一个符合条件的节点
find_all_previous() 方法返回所有符合条件的节点, find_previous() 方法返回第一个符合条件的节点.
CSS选择器:对于熟悉css选择器的开发人员来说,使用这种方法来查找比较简单:
|
|
通过tag标签逐层查找:
|
|
找到某个tag标签下的直接子标签 [6] :
|
|
找到兄弟节点标签:
|
|
通过CSS的类名查找:
|
|
通过tag的id查找:
|
|
同时用多种CSS选择器查询元素:
|
|
通过是否存在某个属性来查找:
|
|
通过属性的值来查找:
|
|
返回查找到的元素的第一个
|
|
修改文档树
Tag.insert() 方法与 Tag.append() 方法类似,区别是不会把新元素添加到父节点 .contents 属性的最后,而是把元素插入到指定的位置.与Python列表总的 .insert() 方法的用法下同:
|
|
Tag.clear() 方法移除当前tag的内容:
|
|
PageElement.extract() 方法将当前tag移除文档树,并作为方法结果返回:
|
|
这个方法实际上产生了2个文档树: 一个是用来解析原始文档的 BeautifulSoup 对象,另一个是被移除并且返回的tag.被移除并返回的tag可以继续调用 extract 方法:
|
|
Tag.decompose() 方法将当前节点移除文档树并完全销毁:
|
|
PageElement.replace_with() 方法移除文档树中的某段内容,并用新tag或文本节点替代它:
|
|
replace_with() 方法返回被替代的tag或文本节点,可以用来浏览或添加到文档树其它地方
PageElement.wrap() 方法可以对指定的tag元素进行包装,并返回包装后的结果:
|
|
该方法在 Beautiful Soup 4.0.5 中添加
Tag.unwrap() 方法与 wrap() 方法相反.将移除tag内的所有tag标签,该方法常被用来进行标记的解包:
|
|
与 replace_with() 方法相同, unwrap() 方法返回被移除的tag